package com.xgk.boot.module.core.controller.admin.truck;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.xgk.boot.framework.apilog.core.annotation.ApiAccessLog;
import com.xgk.boot.framework.common.constant.ErrorCodeConstants;
import com.xgk.boot.framework.common.exception.util.ServiceExceptionUtil;
import com.xgk.boot.framework.common.pojo.CommonResult;
import com.xgk.boot.framework.common.pojo.PageParam;
import com.xgk.boot.framework.common.pojo.PageResult;
import com.xgk.boot.framework.common.util.file.ElmFileUtils;
import com.xgk.boot.framework.common.util.object.BeanUtils;
import com.xgk.boot.framework.excel.core.util.ExcelUtils;
import com.xgk.boot.framework.security.core.util.SecurityFrameworkUtils;
import com.xgk.boot.framework.tenant.core.aop.TenantIgnore;
import com.xgk.boot.framework.translate.core.TranslateUtils;
import com.xgk.boot.module.core.controller.admin.logger.vo.operatelog.OperateLogPageReqVO;
import com.xgk.boot.module.core.controller.admin.logger.vo.operatelog.OperateLogRespVO;
import com.xgk.boot.module.core.controller.admin.truck.vo.*;
import com.xgk.boot.module.core.dal.dto.TruckOrderDto;
import com.xgk.boot.module.core.dal.entity.logger.OperateLogDO;
import com.xgk.boot.module.core.dal.entity.truck.*;
import com.xgk.boot.module.core.logistics.service.TruckOrderCommonService;
import com.xgk.boot.module.core.service.permission.UserRoleServiceImpl;
import com.xgk.boot.module.core.service.truck.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import static com.xgk.boot.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static com.xgk.boot.module.infra.framework.file.core.utils.FileTypeUtils.writeAttachment;

@Slf4j
@Tag(name = "管理后台 - 卡车订单管理")
@RestController("adminTruckOrderController")
@RequestMapping("/system/truck-order")
public class TruckOrderController {

    @Resource
    private TruckOrdersServiceImpl truckOrdersService;
    @Resource
    private TruckOrderBoxServiceImpl boxService;
    @Resource
    private TruckOrderFeeDetailServiceImpl feeDetailService;
    @Resource
    private TruckOrderLogServiceImpl truckOrderLogService;
    @Resource
    private TruckOrderTrackServiceImpl truckOrderTrackService;
    @Resource
    private UserRoleServiceImpl userRoleService;
    @Resource
    private TruckOrderCommonService truckOrderCommonService;
    @Resource
    private TruckOrderBolServiceImpl truckOrderBolService;




    @GetMapping("/get/{orderCode}")
    @Operation(summary = "获得订单详情")
    @Parameter(name = "orderCode", description = "订单code", required = true, example = "1934923143484133377")
    public CommonResult<TruckOrderBaseVO> getOrderInfo(@PathVariable("orderCode") String orderCode) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin && !truckOrdersService.checkOrderPermission(orderCode)) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_NO_PERMISSION, orderCode);
        }
        TruckOrderBaseVO truckOrderBaseVO = truckOrdersService.getTruckOrderBaseVO(orderCode);
        return CommonResult.success(truckOrderBaseVO);
    }

    @GetMapping("/refresh/{orderCode}")
    @Operation(summary = "同服务商同步订单信息")
    @Parameter(name = "orderCode", description = "订单code", required = true, example = "1934923143484133377")
    public CommonResult<TruckOrderBaseVO> refreshOrderInfo(@PathVariable("orderCode") String orderCode) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin && !truckOrdersService.checkOrderPermission(orderCode)) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_NO_PERMISSION, orderCode);
        }
        TruckOrderDto truckOrderDto = truckOrdersService.factoryOrderDto(orderCode);
        truckOrderCommonService.getOrderDetail(truckOrderDto);
        truckOrderCommonService.getOrderTracking(truckOrderDto);
        truckOrderCommonService.getOrUpdateOrderBol(truckOrderDto);
//        TruckOrderBaseVO truckOrderBaseVO = truckOrdersService.getTruckOrderBaseVO(orderCode);
        return CommonResult.success(null);
    }

    @GetMapping("/refresh-bol/{orderCode}")
    @Operation(summary = "同服务商同步提到信息")
    @Parameter(name = "orderCode", description = "订单code", required = true, example = "1934923143484133377")
    public CommonResult<TruckOrderBaseVO> refreshOrderBol(@PathVariable("orderCode") String orderCode) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin && !truckOrdersService.checkOrderPermission(orderCode)) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_NO_PERMISSION, orderCode);
        }
        TruckOrderDto truckOrderDto = truckOrdersService.factoryOrderDto(orderCode);
        truckOrderCommonService.getOrUpdateOrderBol(truckOrderDto);
        return CommonResult.success(null);
    }

    @PostMapping("/cancel")
    @Operation(summary = "申请取消订单详情")
    public CommonResult<TruckOrderVO> cancelOrder(@Valid @RequestBody TruckOrderCancelVO cancelVO) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin && !truckOrdersService.checkOrderPermission(cancelVO.getOrderCode())) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_NO_PERMISSION, cancelVO.getOrderCode());
        }
        TruckOrdersDO ordersDO = truckOrdersService.applyCancelOrder(cancelVO.getOrderCode(), cancelVO.getCancelReason());
        return CommonResult.success(BeanUtils.toBean(ordersDO, TruckOrderVO.class));
    }

    @PostMapping("/approval")
    @Operation(summary = "取消订单进行审批")
    public CommonResult<TruckOrderVO> approvalOrder(@Valid @RequestBody TruckOrderApprovalVO approvalVO) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin ) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.BIZ_NO_PREMISSION_OPERATION);
        }
        TruckOrdersDO ordersDO = truckOrdersService.approveCancelOrder(approvalVO);
        return CommonResult.success(BeanUtils.toBean(ordersDO, TruckOrderVO.class));
    }


    @PostMapping("/page")
    @Operation(summary = "分页获得订单列表")
    public CommonResult<PageResult<TruckOrderVO>> pageList(@Valid @RequestBody TruckOrderReqVO orderReqVO) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin ) {
            // 非管理员只能查询自己账号下订单
            orderReqVO.setCustomerCode(SecurityFrameworkUtils.getLoginUser().getUsername());
        }
        PageResult<TruckOrderVO> truckOrdersDOPageResult = truckOrdersService.pageTruckOrders(orderReqVO);
        return CommonResult.success(truckOrdersDOPageResult);
    }

    @PostMapping("/bol/page")
    @Operation(summary = "分页获订单提单信息")
    public CommonResult<PageResult<TruckOrderBolVO>> pageListBols(@Valid @RequestBody TruckOrderOtherReqVO orderReqVO) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        String orderCode = orderReqVO.getOrderCode();
        if( !currentUserAdmin && !truckOrdersService.checkOrderPermission(orderCode)) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_NO_PERMISSION, orderCode);
        }

        if(truckOrderBolService.ifUpdateBol(orderCode)){
            try{
                TruckOrderDto truckOrderDto = truckOrdersService.factoryOrderDto(orderCode);
                truckOrderCommonService.getOrUpdateOrderBol(truckOrderDto);
            }catch (Exception e){
                log.error(String.format("update order {%s} bol error",orderCode),e);
            }
        }

        PageResult<TruckOrderBolDO> truckOrderBolDOPageResult = truckOrderBolService.pageTruckOrderBols(orderReqVO);
        return CommonResult.success(BeanUtils.toBean(truckOrderBolDOPageResult, TruckOrderBolVO.class));
    }

    @PostMapping("/log/page")
    @Operation(summary = "分页获订单日志信息")
//    @PreAuthorize("@ss.hasPermission('system:admin')")
    public CommonResult<PageResult<TruckOrderLogVO>> pageListLogs(@Valid @RequestBody TruckOrderOtherReqVO orderReqVO) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin && !truckOrdersService.checkOrderPermission(orderReqVO.getOrderCode())) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_NO_PERMISSION, orderReqVO.getOrderCode());
        }
        PageResult<TruckOrderLogDO> truckOrderLogDOPageResult = truckOrderLogService.pageOrdersLogs(orderReqVO);
        PageResult<TruckOrderLogVO> bean = BeanUtils.toBean(truckOrderLogDOPageResult, TruckOrderLogVO.class);
        return CommonResult.success(bean);
    }

    @PostMapping("/box/page")
    @Operation(summary = "分页获订单货物信息")
//    @PreAuthorize("@ss.hasPermission('system:admin')")
    public CommonResult<PageResult<TruxkOrderBoxVO>> pageListBoxes(@Valid @RequestBody TruckOrderOtherReqVO orderReqVO) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin && !truckOrdersService.checkOrderPermission(orderReqVO.getOrderCode())) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_NO_PERMISSION, orderReqVO.getOrderCode());
        }
        PageResult<TruckOrderBoxDO> truckOrderBoxDOPageResult = boxService.pageTruckOrders(orderReqVO);
        return CommonResult.success(BeanUtils.toBean(truckOrderBoxDOPageResult, TruxkOrderBoxVO.class));
    }

    @PostMapping("/track/page")
    @Operation(summary = "分页获订单物流信息信息")
    public CommonResult<PageResult<TruckOrderTrackVO>> pageListTracks(@Valid @RequestBody TruckOrderOtherReqVO orderReqVO) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin && !truckOrdersService.checkOrderPermission(orderReqVO.getOrderCode())) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_NO_PERMISSION, orderReqVO.getOrderCode());
        }
        PageResult<TruckOrderTrackDO> truckOrderLogDOPageResult = truckOrderTrackService.pageOrderTrack(orderReqVO);
        PageResult<TruckOrderTrackVO> bean = BeanUtils.toBean(truckOrderLogDOPageResult, TruckOrderTrackVO.class);
        return CommonResult.success(bean);
    }

    @PostMapping("/fee/page")
    @Operation(summary = "获得订单费用详情")
    public CommonResult<PageResult<TruckOrderFeeDetailVO>> getOrderFeeInfo(@Valid @RequestBody TruckOrderOtherReqVO orderReqVO) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin && !truckOrdersService.checkOrderPermission(orderReqVO.getOrderCode())) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.COMMON_NO_PERMISSION, orderReqVO.getOrderCode());
        }
        PageResult<TruckOrderFeeDetailDO> truckOrderLogDOPageResult = feeDetailService.pageOrdersFees(orderReqVO);
        PageResult<TruckOrderFeeDetailVO> bean = BeanUtils.toBean(truckOrderLogDOPageResult, TruckOrderFeeDetailVO.class);
        return CommonResult.success(bean);
    }

    @PostMapping("/fee_info/page")
    @Operation(summary = "获得订单费用详情")
    public CommonResult<PageResult<TruckOrderFeeDetailVO>> getPageOrderFeeInfo(@Valid @RequestBody TruckOrderFeeDetailReqVo orderReqVO) {
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin ) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            orderReqVO.setCustomerCode(SecurityFrameworkUtils.getLoginUser().getUsername());
        }
        PageResult<TruckOrderFeeDetailDO> truckOrderLogDOPageResult = feeDetailService.pageListOrdersFees(orderReqVO);
        PageResult<TruckOrderFeeDetailVO> bean = BeanUtils.toBean(truckOrderLogDOPageResult, TruckOrderFeeDetailVO.class);
        return CommonResult.success(bean);
    }

    @PostMapping("/fee_info")
    @Operation(summary = "增加订单扩展费用")
    @PreAuthorize("@ss.hasPermission('system:admin')")
    public CommonResult<Boolean> addOrderExtendFeeInfo(@Valid @RequestBody TruckOrderFeeDetailVO orderReqVO) {
        boolean b = feeDetailService.addOrderFee(orderReqVO);
        return CommonResult.success(b);
    }

    @DeleteMapping("/fee_info/{id}")
    @Operation(summary = "删除订单扩展费用")
    @PreAuthorize("@ss.hasPermission('system:admin')")
    public CommonResult<Boolean> deleteOrderExtendFeeInfo(@PathVariable("id") String id) {
        boolean b = feeDetailService.deleteOrderFee(id);
        return CommonResult.success(b);
    }


    @GetMapping("/fee_info/export")
    @ApiAccessLog(operateType = EXPORT)
    public void exportFeeInfo(HttpServletResponse response,  TruckOrderFeeDetailReqVo orderReqVO) throws IOException {
        orderReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        Boolean currentUserAdmin = userRoleService.isCurrentUserAdmin();
        if( !currentUserAdmin ) {
            // 非管理员查询自己账号下订单,检查是有查询该订单的权限
            orderReqVO.setCustomerCode(SecurityFrameworkUtils.getLoginUser().getUsername());
        }
        PageResult<TruckOrderFeeDetailDO> truckOrderLogDOPageResult = feeDetailService.pageListOrdersFees(orderReqVO);
        List list = BeanUtils.toBean(truckOrderLogDOPageResult.getData(), TruckOrderFeeDetailExport.class);
        ExcelUtils.write(response, "账单列表.xls", "账单", TruckOrderFeeDetailExport.class,
                TranslateUtils.translate(list));
    }


//    @PermitAll
    @GetMapping("/bol/download/{id}")
    @TenantIgnore
    @Operation(summary = "提单下载文件")
    @Parameter(name = "id", description = "提单文件id", required = true)
    public void getFileContent(HttpServletRequest request,
                               HttpServletResponse response,
                               @PathVariable("id") Long id) throws Exception {

        TruckOrderBolDO byId = truckOrderBolService.getById(id);
        if(byId==null){
            log.error("can't find id:"+id);
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "file:"+id);
            return;
        }
        // 1. 安全检查：防止路径遍历攻击（如../../../etc/passwd）
        if (!FileUtil.exist(byId.getOlPath())) {
            log.error("can't find file:"+byId.getOlPath());
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "文件不存在:"+byId.getOlPath());
            return;
        }

        File file = FileUtil.file(byId.getOlPath());
        // 3. 设置响应头
        String fileName = FileUtil.getName(file);
        String contentType = ElmFileUtils.getContentTypeByFileName(fileName);
        //默认下载模式（不预览，预览模式为：inline）
        String contentDisposition =  "attachment";
        response.setContentType(contentType);
        response.setHeader("Content-Disposition", contentDisposition + "; filename=\"" + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20") + "\"");
        response.setContentLengthLong(file.length());

        // 4. 流式输出文件内容
        try (BufferedInputStream bis = FileUtil.getInputStream(file);
             BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream())) {

            byte[] buffer = new byte[1024 * 8];
            int len;
            while ((len = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            bos.flush();
        } catch (IOException e) {
            log.error("文件下载被用户取消或网络中断: {}", fileName, e);
            // 通常不需要处理，客户端断开连接会抛出异常
        }
    }




}
